import re

from core.error import QueryDynamicVariableError
from core.logger.logger import logger


class Dynamic:


    @classmethod
    def __query_dynamic_variable(cls, obj, patten=r"\$\{[\w().,\"\'\s]+\}"):
        return re.findall(patten, obj)

    @classmethod
    def replace_variable(cls, obj, storage: list):
        """
        :param obj: 待处理的数据，可以传入字符串，也可以是列表、字典
        :param storage: 数据存储的对象，动态变量会从此对象中获取数据。
                        以列表形式传入，会遍历列表中每个对象中找出合
                        适的属性。
        """
        # 如果待处理的对象是字符串，例如url，直接进行替换。
        if isinstance(obj, str):
            obj = cls.__replace(obj, storage)

            # 为了应对嵌套使用动态变量的场景
            # 再次进行正则匹配，如果有就递归
            if cls.__query_dynamic_variable(obj):
                obj = cls.replace_variable(obj, storage)
            return obj

        # 如果待处理是列表或字典等，遍历然后进行递归
        if isinstance(obj, (list, tuple, set)):
            for ind, variable in enumerate(obj):
                if isinstance(variable, (list, tuple, set, dict, str)):
                    obj[ind] = cls.replace_variable(obj, storage)

        if isinstance(obj, dict):
            for key, val in obj.items():
                if isinstance(val, (list, tuple, set, dict, str)):
                    obj[key] = cls.replace_variable(val, storage)
        return obj

    @classmethod
    def __replace(cls, obj, storage):
        log = logger.get_logger("ProcessorLogs")
        dynamic_variable_list = cls.__query_dynamic_variable(obj)
        for variable in dynamic_variable_list:
            # 移除变量的前缀"${"和后缀"}"
            attr_name = cls.__remove_prefix_and_suffix(variable, "${", "}")
            func_param = cls.__query_dynamic_variable(attr_name, r"\(.*?\)")
            if func_param:
                func_param = func_param[0]
                attr_name = attr_name.replace(func_param, "")

                param_list = func_param.split(",")
                if len(param_list) == 1:
                    param = param_list[0]
                    param = cls.__remove_prefix_and_suffix(param, "(", ")")
                else:
                    param = func_param
            else:
                param = False
            for st in storage:
                # 判断动态变量是否在类中
                if hasattr(st, attr_name):
                    var = getattr(st, attr_name)
                    # 判断从类中获取回来的变量是否是一个可调用的对象
                    # 不是的话直接取值然后做替换
                    if callable(var):
                        # 判断参数是有多个、单个、还是无参数
                        if len(param) > 1:
                            attr = var(*eval(str(param)))
                        elif param:
                            attr = var(param)
                        else:
                            attr = var()
                        obj = obj.replace(variable, str(attr))
                    else:
                        obj = obj.replace(variable, str(var))
                    return obj
            else:
                log.error(f"无法从给定的存储对象里面找到动态变量{attr_name}")
                raise QueryDynamicVariableError(f"无法从给定的存储对象里面找到动态变量{attr_name}")

    @classmethod
    def __remove_prefix_and_suffix(cls, obj, prefix=None, suffix=None):
        """移除字符串的前缀和后缀"""
        param = obj
        if prefix is not None:
            param = param.removeprefix(prefix)
        if suffix is not None:
            param = param.removesuffix(suffix)
        return param
